<?php

namespace Core\init;

use Core\annotations\Bean;
use Core\BeanFactory;
use Illuminate\Database\Capsule\Manager;

/**
 * @Bean
 * @method \Illuminate\Database\Query\Builder table(\Closure|\Illuminate\Database\Query\Builder|string $table, string|null $as = "", string|null $connection = "")
 */
class MyDb
{
    private $Db;
    private $DbSource = "default";
    public $transactionDb = false;

    /**
     * @var PdoPool
     */
    private $pdoPool;

    /**
     * @return mixed
     */
    public function getDbSource()
    {
        return $this->DbSource;
    }

    /**
     * @param mixed $DbSource
     */
    public function setDbSource($DbSource): void
    {
        $this->DbSource = $DbSource;
    }

    /**
     *
     * MyDb constructor.
     * @param bool $db [事务开启时 的DB对象]
     * @param bool $pdoPool [事务开启时 的连接池]
     * @throws \DI\DependencyException
     * @throws \DI\NotFoundException
     * @throws \Throwable
     */
    public function __construct($db = false, $pdoPool = false)
    {
        global $GLOBALS_CONFIGS;
        if (isset($GLOBALS_CONFIGS['db'])) {
            $this->Db = new Manager();
            foreach ($GLOBALS_CONFIGS['db'] as $key => $value) {
                $this->Db->addConnection(
                    $value,
                    $key
                );
            }
            $this->Db->setAsGlobal();
            $this->Db->bootEloquent();
        }
        //非事务 才生产连接池  否则会产生多余的链接
        if (!$pdoPool) {
            $pdoPool = BeanFactory::getBean(PdoPool::class);
            $pdoPool->init();
        }
        $this->pdoPool = $pdoPool;
        $this->transactionDb = $db;
        if ($db) {
            //事务开启 需设置PDO 对象及开启事务
            $this->Db->getConnection($this->DbSource)->setPdo($this->transactionDb->db);
            $this->Db->getConnection($this->DbSource)->beginTransaction();
        }
    }

    /**
     * 开启事务
     * @return MyDb
     * @throws \DI\DependencyException
     * @throws \DI\NotFoundException
     * @throws \Throwable
     */
    public function Begin()
    {
        //返回 MYDB 对象 操作事务
        return new self($this->pdoPool->getConnect(), $this->pdoPool);
    }

    /**
     * 事务提交
     * @throws \Throwable
     */
    public function commit()
    {
        try {
            $this->Db->getConnection($this->DbSource)->commit();
        } catch (\Exception $exception) {
            throw $exception;
        } finally {
            if ($this->transactionDb) {
                $this->pdoPool->close($this->transactionDb);
                $this->transactionDb = false;
            }
        }
    }

    /**
     * 事务回滚
     * @throws \Throwable
     */
    public function rollBack()
    {
        try {
            $this->Db->getConnection($this->DbSource)->rollBack();
        } catch (\Exception $exception) {
            throw $exception;
        } finally {
            if ($this->transactionDb) {
                $this->pdoPool->close($this->transactionDb);
                $this->transactionDb = false;
            }
        }
    }

    /**
     * 调用ORM 相关方法
     * @param $methodName
     * @param $arguments
     * @return array
     */
    public function __call($methodName, $arguments)
    {
        //判断当前是否事务执行
        $isTransaction = false;
        if ($this->transactionDb) {
            $pdo_object = $this->transactionDb;
            $isTransaction = true;
        } else {
            $pdo_object = $this->pdoPool->getConnect();
        }
        try {
            if (!$pdo_object) {
                return [];
            }
            //非事务需要设置PDO 对象
            if (!$isTransaction) {
                $this->Db->getConnection($this->DbSource)->setPdo($pdo_object->db);
            }
            return $this->Db->getConnection($this->DbSource)->$methodName(...$arguments);
        } catch (\Exception $exception) {
            echo "异常信息:" . $exception->getMessage() . ",异常文件:" . $exception->getFile() . ",异常行数:" . $exception->getLine();
        } finally {
            if ($pdo_object && !$isTransaction) {
                $this->pdoPool->close($pdo_object);
            }
        }
    }

    /**
     * 释放连接
     * @param $pdoObj
     */
    public function releaseConnect($pdoObj)
    {
        if ($pdoObj && !$this->transactionDb) {
            $this->pdoPool->close($pdoObj);
        }
    }

    /**
     * 借一个连接
     * @return bool|mixed
     */
    public function genConnect()
    {
        $isTransaction = false;
        if ($this->transactionDb) {
            $pdo_object = $this->transactionDb->db;
            $isTransaction = true;
        } else {
            $pdo_object = $this->pdoPool->getConnect();
        }
        //非事务需要设置PDO 对象
        if ($pdo_object && !$isTransaction) {
            $this->Db->getConnection($this->DbSource)->setPdo($pdo_object->db);
            return $pdo_object;
        }
        return false;
    }

}
